-- 在 Vim 中，vim.keymap.set() 函数用于设置键盘映射。
-- 键盘映射规则对象可以包含以下属性：
--     lhs（必需）：左侧键序列，即触发映射的按键序列。可以是单个字符、特殊键（如 <CR> 表示回车键）、组合键（如 <C-x> 表示 Ctrl + X）或者按键序列的组合（如 <C-w><C-w> 表示连按两次 Ctrl + W）。
--     rhs（必需）：右侧键序列，即按下左侧键序列时将执行的操作。可以是普通的按键序列、Ex 命令或者调用 Vim 函数。
--     mode（可选）：适用的编辑模式。可以是 "n"（Normal 模式）、"i"（Insert 模式）、"v"（Visual 模式）、"s"（Select 模式）、"x"（Visual 模式、块选择模式）、"o"（Operator-pending 模式）或者它们的组合。如果未指定模式，则适用于所有模式。
--     noremap（可选）：如果设置为 true，则禁用递归映射，意味着执行映射时不会再次触发其他映射规则。
--     silent（可选）：如果设置为 true，则在执行映射时禁用显示命令。
--     expr（可选）：如果设置为 true，则将右侧键序列解释为表达式。这使您可以使用 Vim 的表达式语言执行更复杂的操作。
-- vim.keymap.set({
--   lhs: 'jk',
--   rhs: '<Esc>',
--   mode: 'i',
--   noremap: true
-- })

local map = vim.keymap.set

-- neovim with OS clipboard
map(
  'v',
  '<A-w>',
  '"+y <cmd>lua vim.notify("Yanked to clipboard!")<CR>',
  { desc = 'Yanked to clipboard', noremap = true, silent = false }
)
map(
  'v',
  '<C-w>',
  '"+x <cmd>lua vim.notify("Cut to clipboard!")<CR>',
  { desc = 'Cut to clipboard', noremap = true, silent = false }
)
map(
  'n',
  '<C-y>',
  '"+p <cmd>lua vim.notify("Pasted from clipboard!")<CR>',
  { desc = 'Pasted from clipboard', noremap = true, silent = false }
)

-- Move to window using the <ctrl> hjkl keys
map('n', '<C-h>', '<C-w>h', { desc = 'Go to left window' })
map('n', '<C-j>', '<C-w>j', { desc = 'Go to lower window' })
map('n', '<C-k>', '<C-w>k', { desc = 'Go to upper window' })
map('n', '<C-l>', '<C-w>l', { desc = 'Go to right window' })

-- Resize window using <ctrl> arrow keys
map('n', '<C-Up>', '<cmd>resize +2<cr>', { desc = 'Increase window height' })
map('n', '<C-Down>', '<cmd>resize -2<cr>', { desc = 'Decrease window height' })
map('n', '<C-Left>', '<cmd>vertical resize -2<cr>', { desc = 'Decrease window width' })
map('n', '<C-Right>', '<cmd>vertical resize +2<cr>', { desc = 'Increase window width' })

-- Move Lines
map('n', '<A-j>', '<cmd>m .+1<cr>==', { desc = 'Move down' })
map('n', '<A-k>', '<cmd>m .-2<cr>==', { desc = 'Move up' })
map('i', '<A-j>', '<esc><cmd>m .+1<cr>==gi', { desc = 'Move down' })
map('i', '<A-k>', '<esc><cmd>m .-2<cr>==gi', { desc = 'Move up' })
map('v', '<A-j>', ":m '>+1<cr>gv=gv", { desc = 'Move down' })
map('v', '<A-k>', ":m '<-2<cr>gv=gv", { desc = 'Move up' })

-- buffer
map('n', '<leader>bb', '<cmd>e #<cr>', { desc = 'Switch to Other Buffer' })
map('n', '<leader>`', '<cmd>e #<cr>', { desc = 'Switch to Other Buffer' })
map('n', '<S-h>', '<cmd>bprevious<cr>', { desc = 'Prev buffer' })
map('n', '<S-l>', '<cmd>bnext<cr>', { desc = 'Next buffer' })
map('n', '[b', '<cmd>bprevious<cr>', { desc = 'Prev buffer' })
map('n', ']b', '<cmd>bnext<cr>', { desc = 'Next buffer' })

-- Clear search with <esc>
map({ 'i', 'n' }, '<esc>', '<cmd>nohlsearch<cr><esc>', { desc = 'Escape and clear hlsearch' })

-- Add undo break-points
map('i', ',', ',<c-g>u')
map('i', '.', '.<c-g>u')
map('i', ';', ';<c-g>u')

-- save file
map({ 'i', 'v', 'n', 's' }, '<C-s>', '<cmd>w<cr><esc>', { desc = 'Save file' })

-- better indenting
map('v', '<', '<gv')
map('v', '>', '>gv')

-- new file
map('n', '<leader>nf', '<cmd>enew<cr>', { desc = 'New File' })

-- quit
map('n', '<leader>qq', '<cmd>qa<cr>', { desc = 'Quit all' })

-- highlights under cursor
if vim.fn.has('nvim-0.9.0') == 1 then
  map('n', '<leader>ip', vim.show_pos, { desc = 'Inspect Pos' })
end

-- windows
map('n', '<leader>ww', '<C-W>p', { desc = 'Other window' })
map('n', '<leader>wd', '<C-W>c', { desc = 'Delete window' })
map('n', '<leader>w-', '<C-W>s', { desc = 'Split window below' })
map('n', '<leader>w|', '<C-W>v', { desc = 'Split window right' })
map('n', '<leader>-', '<C-W>s', { desc = 'Split window below' })
map('n', '<leader>|', '<C-W>v', { desc = 'Split window right' })

-- tabs
map('n', '<leader><tab>l', '<cmd>tablast<cr>', { desc = 'Last Tab' })
map('n', '<leader><tab>f', '<cmd>tabfirst<cr>', { desc = 'First Tab' })
map('n', '<leader><tab><tab>', '<cmd>tabnew<cr>', { desc = 'New Tab' })
map('n', '<leader><tab>]', '<cmd>tabnext<cr>', { desc = 'Next Tab' })
map('n', '<leader><tab>d', '<cmd>tabclose<cr>', { desc = 'Close Tab' })
map('n', '<leader><tab>[', '<cmd>tabprevious<cr>', { desc = 'Previous Tab' })

vim.api.nvim_create_autocmd('LspAttach', {
  callback = function(ev)
    -- lsp
    map('n', '<leader>e', vim.diagnostic.open_float, { desc = 'diagnostic open_float' })
    map('n', '[d', vim.diagnostic.goto_prev, { desc = 'diagnostic goto_prev' })
    map('n', ']d', vim.diagnostic.goto_next, { desc = 'diagnostic goto_next' })
    map('n', '<leader>l', vim.diagnostic.setloclist, { desc = 'diagnostic list' })
    map({ 'i', 'n' }, '<C-k>', vim.lsp.buf.signature_help, { buffer = ev.buf, silent = true, desc = 'Signature help' })
  end,
})
